#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>

#include "server.h"

/*
INT8 pBakRcvBuf[NET_BUF_SIZE] = {0};
*/
PASS_MSG pRecvMsg;

INT32 service_termClient(INT32 sfd)
{
	INT32 r, fd, tsfd, ix;
	UINT16 n, ta, tb = 2;
	DEV_NET s_netMa = {0};
	PASS_MSG tSendMsg;	
	JT808_MSG_PKG Jt808_msgPkg = {0};
	INT8 tBakRcvBuf[NET_BUF_SIZE] = {0};
	INT8 sim[12] = {0}, sql_cmd[BUF_SIZE] = {0};

	r = disconnect_judge(sfd, 500);
	if(r == -1){
		r = link_sfd_search(head, sfd, sim);
		if(r == -1){
			E(" search error or cant't find.");
			return -1;
		}
		sprintf(sql_cmd, "update vehicle set online = 0 where sim = '%s';", sim);
		r = mysql_fun(sql_cmd);
		sprintf(sql_cmd, "update vehicle set sim = NULL where sim = '%s';", sim);
		r = mysql_fun(sql_cmd);
		return -1;
	}
	
	r = recv(sfd, s_netMa.rcvBuf, sizeof(s_netMa.rcvBuf), 0);
	if(r == -1 && errno == EINTR)
		return 0;
	if(r == -1)
		return -1;

	for(ix = 0; ix < r; ix++){
		fprintf(stdout, "%02x ", s_netMa.rcvBuf[ix]);
		//change
		fprintf(stderr, "%02x ", s_netMa.rcvBuf[ix]);
	}
	putchar('\n');
	fputc('\n', stderr);
	memcpy(tBakRcvBuf, s_netMa.rcvBuf, r);
	memset(s_netMa.rcvBuf, 0, sizeof(s_netMa.rcvBuf));

	r = assign_jt808msg(&Jt808_msgPkg, tBakRcvBuf, r);
	if(r == -1){
		E(" Message assign error.");
		return -1;
	}

	r = msg_analyze(&Jt808_msgPkg, sfd);
	if(r == -1){
		E(" Msg_analyze error.");
		return -1;
	}
	E(" Good status terminal...123...");
#if 0
	fd = open(NAME_FIFO_1, O_RDONLY | O_NONBLOCK, 0);
	if(fd == -1){
		perror("open().");
		return 0;
	}

	if((r = read(fd, &tSendMsg, sizeof(tSendMsg))) == -1)
	{
		if(errno == EAGAIN)
			E(" Fifo1 not data yet.");
		return -1;
	}
	E(" Read_fifo sim:%s msgId:%x", tSendMsg.sim, tSendMsg.msgId);	
	tsfd = link_sim_search(head, tSendMsg.sim);
	if(tsfd == -1){
		E(" Link_node_search error.");
		return -1;
	}
	else if(tsfd == 0){
		E(" Can't find and vehicle offline.");
	}
	else{
		for(n = 0; n < 3; n++){
			r = platf_msg_assem(tSendMsg.pbody, strlen(tSendMsg.pbody), &tSendMsg, tsfd);
			if(r == -1){
				E(" Platf_msg_assem error.");
				return -1;
			}
			ta = tb*(n + 1);
			tb = ta;
			r = disconnect_judge(tsfd, ta);
			if(r == 0)
				break;
		}
	}
#endif
	return 0;
}

INT32 service_platfClient(INT32 sfd)
{
	INT32 r, len = 0;
	INT32 ix, count = 0;	
	DEV_NET s_netSla = {0};
	INT8 *ptr = s_netSla.rcvBuf;
	INT8 bakRcvBuf[NET_BUF_SIZE] = {0};

	r = disconnect_judge(sfd, 5);
	if(r == -1)
		return -1;
	r = recv(sfd, s_netSla.rcvBuf, sizeof(s_netSla.rcvBuf), 0);
	if(r == -1){
		E(" Fail to recived.");
		return -1;
	}
	//	memcpy(pbakRcvBuf, s_netMa.rcvBuf, r);
	//	memset(s_netMa.rcvBuf, 0, sizeof(s_netMa.rcvBuf));
	while(*ptr){
		if(*ptr == ';')
			count++;
		ptr++;
	}

	E(" count: %d", count);
	for(ix = 0; ix < count; ix++){
		r = split_platfMsg(&s_netSla.rcvBuf[len], bakRcvBuf, ';');
		if(r == -1){
			return -1;
		}
		len += r;
		E(" recived msg: %s r: %d", bakRcvBuf, r);
		r = platfMsg_handle(bakRcvBuf, r, sfd);
		memset(bakRcvBuf, 0, sizeof(bakRcvBuf));
	}
	E(" Good status platform...123...");
	return 0;
}

//service terminal thread.
void *service_termThread(void *arg)
{
	INT32 r;
	CLIENT *c = (CLIENT *)arg;
	SERVER *s = c->server;

	for(; ;){
		r = service_termClient(c->sfd);
		if(r == -1){
			E(" Failed to server client.");
			break;
		}
	}
	
	pthread_mutex_lock(&s->lock);
	s->nr_client--;
	pthread_mutex_unlock(&s->lock);
	close(c->sfd);
	r = link_node_delet(head, c->sfd);
	if(r == -1){
		E(" not find and delete error.");
	}

	D(" Disconnect - Descriptor %d.", c->sfd);
	pthread_exit(NULL);
}

//service platform thread.
void *service_platfThread(void *arg)
{
	INT32 r;
	CLIENT *c = (CLIENT *)arg;
	SERVER *s = c->server;

	for(; ;){
		r = service_platfClient(c->sfd);
		if(r == -1){
			E(" Failed to server client.");
			break;
		}
	}
	
	pthread_mutex_lock(&s->lock);
	s->nr_client--;
	pthread_mutex_unlock(&s->lock);
	close(c->sfd);

	D(" Disconnect - Descriptor %d.", c->sfd);
	pthread_exit(NULL);
}

INT32 server_new_client(SERVER *s, void *(*pFun)(void *))
{
	INT32 sfd;
	INT32 r;
	CLIENT *c;

	for( ; ;){
		sfd = accept(s->listen_sfd, NULL, NULL);
		if(sfd == -1 && errno == EINTR)
			continue;
		if(sfd == -1){
			perror("accept().");
			return -1;
		}
		break;
	}
	D(" Accept socket descriptor: %d.", sfd);
	
	pthread_mutex_lock(&s->lock);
	if(s->nr_client == MAX_NR_SFD){
		close(sfd);
		D(" Max limit reached.");

		pthread_mutex_unlock(&s->lock);
		return -1;
	}
	pthread_mutex_unlock(&s->lock);

	c = (CLIENT *)malloc(sizeof(CLIENT));
	if(NULL == c){
		E(" Malloc error.");
		close(sfd);
		return -1;
	}

	c->server = s;
	c->sfd = sfd;

	r = pthread_create(&c->pth, NULL, pFun, (void *)c);
	if(r != 0){
		E(" Failed to create pthread.");
		close(sfd);

		free(c);
		c = NULL;

		return -1;
	}

	pthread_detach(c->pth);
	
	pthread_mutex_lock(&s->lock);
	s->nr_client++;
	pthread_mutex_unlock(&s->lock);

	D(" Number of client: %d.", s->nr_client);

	return 0;
}

INT32 server_init(SERVER *s, NET_ADDR *addr)
{
	struct sockaddr_in serv_addr;
	socklen_t addrlen;
	INT32 r;

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(addr->servPort);

	r = inet_pton(AF_INET, addr->servIp, &serv_addr.sin_addr);
	if(r == -1){
		perror("inet_pton().");
		return -1;
	}

	s->listen_sfd = socket(AF_INET, SOCK_STREAM, 0);
	if(s->listen_sfd == -1){
		perror("socket().");
		return -1;
	}
	
	r = 1;
	r = setsockopt(s->listen_sfd, SOL_SOCKET, SO_REUSEADDR, &r, sizeof(r));
	if(r == -1){
		perror("setsockopt().");
		return -1;
	}

	addrlen = sizeof(serv_addr);
	r = bind(s->listen_sfd, (struct sockaddr *)&serv_addr, addrlen);	
	if(r == -1){
		perror("bind().");
		return -1;
	}

	r = listen(s->listen_sfd, BACKLOG);
	if(r == -1){
		perror("listen().");
		return -1;
	}

	s->nr_client = 0;
	pthread_mutex_init(&s->lock, NULL);
	D(" IP: %s, Port: %u.", addr->servIp, addr->servPort);

	return 0;
}

